package com.yanqu.road.utils.property;

import com.yanqu.road.utils.RandomHelper;
import com.yanqu.road.utils.string.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class PropertyHelper {

	private static Logger logger = LogManager.getLogger(PropertyHelper.class.getName());
	private static RandomHelper randomHelper = new RandomHelper();

	/**
	 * 把扣除数量0的道具移出去
	 * （扣道具那边没处理道具扣除数量0且玩家从没获得这个道具的情况）
	 */
	public static void removeZeroGoods(Property property) {
		List<Integer> removeId = new ArrayList<>();
		for (Map.Entry<Integer, BigInteger> entry : property.getGoods().entrySet()) {
			if (entry.getValue().compareTo(BigInteger.ZERO) == 0) {
				removeId.add(entry.getKey());
			}
		}
		for (Integer id : removeId) {
			property.removeProperty(id);
		}
	}

	/**
	 * 道具配置新格式
	 * 格式：道具1=数量;道具5＝数量;道具6=数量,权重#道具2=数量,权重|道具3=数量,权重#道具4=数量,权重|...
	 * “|”区分池子，“#”区分每个池子里不同的道具组合的权重，“;”表示一个道具组合里有多少种道具
	 * 道具3和4就是一个池子里的两个道具，有权重的时候，就是在这两个道具里随机
	 * 如果每个池子里只有一个道具那就是固定奖励，举例子“道具1=数量,权重|道具2=数量,权重”
	 * 程序取道具的时候，就是每个池子都读取，然后根据池子里是只有一个道具或者多个道具来判断每个池子里取啥道具
	 */
	public static Property parseNewStringToProperty(String propertyStr) {
		Property property = new Property();
		if (StringUtils.isNullOrEmpty(propertyStr) || "0".equals(propertyStr)) {
			return property;
		}
		propertyStr = propertyStr.trim();
		List<String>  rewardGroupList = StringUtils.stringToStringList(propertyStr, "\\|");
		for (String rewardGroup : rewardGroupList) {
			List<String> rewardParamItems = StringUtils.stringToStringList(rewardGroup, "#");
			// 总权重
			int sumWeight = 0;
			for (String rewardParamItem : rewardParamItems) {
				String[] split = rewardParamItem.split(",");
				sumWeight += Integer.parseInt(split[1]);
			}
			// 随机一个权重
			int randomWeight = (int) (Math.random() * sumWeight);
			// 当前权重
			int curWeight = 0;
			for (String rewardParamItem : rewardParamItems) {
				String[] split = rewardParamItem.split(",");
				if (split.length < 2) {//做下长度判断,兼容一下不配权重的。
					curWeight += 1;
				} else {
					curWeight += Integer.parseInt(split[1]);
				}
				if (randomWeight < curWeight) {
					property.addProperty(parseStringToProperty(split[0]));
					break;
				}
			}
		}
		return property;
	}

	/**
	 * 道具配置新格式
	 *
	 * @param propertyStr
	 * @return
	 */
	public static List<List<Property>> parseNewStringToPropertyList(String propertyStr) {
		List<List<Property>> list = new ArrayList<>();
		if (StringUtils.isNullOrEmpty(propertyStr) || "0".equals(propertyStr)) {
			return list;
		}
		propertyStr = propertyStr.trim();
		List<String> rewardGroupList = StringUtils.stringToStringList(propertyStr, "\\|");
		for (String rewardGroup : rewardGroupList) {
			List<Property> propertyList = new ArrayList<>();

			List<String> rewardParamItems = StringUtils.stringToStringList(rewardGroup, "#");
			// 总权重
			int sumWeight = 0;
			for (String rewardParamItem : rewardParamItems) {
				String[] split = rewardParamItem.split(",");
				Property property = parseStringToProperty(split[0]);
				if (split.length < 2) {//做下长度判断,兼容一下不配权重的。
					sumWeight += 1;
				} else {
					sumWeight += Integer.parseInt(split[1]);
				}
				property.setWeightsAdd(sumWeight);

				propertyList.add(property);
			}
			list.add(propertyList);
		}
		return list;
	}

	/**
	 * 随机奖励
	 *
	 * @return
	 */
	public static Property randomPropertyByListList(List<List<Property>> listList) {
		Property property = new Property();
		if (listList == null || listList.size() == 0) {
			return property;
		}

		for (List<Property> list : listList) {
			// 总权重
			int sumWeight = list.get(list.size() - 1).getWeightsAdd();
			// 随机一个权重
			int randomWeight = (int) randomHelper.nextLong(sumWeight);
			for (Property p : list) {
				if (randomWeight < p.getWeightsAdd()) {
					property.addProperty(p);
					break;
				}
			}
		}
		return property;
	}


	public static Property parseStringToProperty(String propertyStr) {
		return parseStringToProperty(propertyStr, ";");
	}

	public static Property parseStringToProperty(String propertyStr, String reqex) {
		if (null != propertyStr && propertyStr.trim().length() > 0) {
			Property property = new Property();
			String[] propertyStrArray = propertyStr.trim().split(reqex);
			for (String arrayStr : propertyStrArray) {
				String goodsStr[] = arrayStr.split("=");
				if (goodsStr.length != 2) {
					continue;
				}
				int goodsId = 0;
				BigInteger value = null;
				try {
					goodsId = Integer.valueOf(goodsStr[0]);
					value = new BigInteger(goodsStr[1]);
				} catch (Exception e) {
					logger.error("异常错误",e);
				}
				property.addProperty(goodsId, value);
			}
			return property;
		} else {
			return null;
		}
	}

	public static String parsePropertyToString(List<Property> propertyList) {
		if(null == propertyList){
			return "";
		}
		Property totalProperty = new Property();
		for (Property property : propertyList) {
			totalProperty.addProperty(property);
		}
		return parsePropertyToString(totalProperty);
	}

	public static String parsePropertyToString(Property property) {
		return parsePropertyToString(property, ";");
	}

	public static String parsePropertyToString(Property property, String reqex) {
		if (property == null) {
			return "";
		}
		StringBuilder propertyStr = new StringBuilder();
		Map<Integer, BigInteger> goodsMap = property.getGoods();
		List<Integer> goodsIdList = new ArrayList<>(goodsMap.keySet());
		for (int goodsId : goodsIdList) {
			BigInteger value = goodsMap.get(goodsId);
			if (value.compareTo(BigInteger.ZERO) > 0) {
				propertyStr.append(parseGoodsToString(goodsId, value)).append(reqex);
			}
		}
		if (propertyStr.length() > 1) {
			return propertyStr.substring(0, propertyStr.length() - 1);
		}else {
			return "";
		}
	}

	public static String parsePropertyMapToString(Map<Integer, BigInteger> goodsMap, String reqex) {
		StringBuilder propertyStr = new StringBuilder();
		List<Integer> goodsIdList = new ArrayList<>(goodsMap.keySet());
		for (int goodsId : goodsIdList) {
			BigInteger value = goodsMap.get(goodsId);
			if (value.compareTo(BigInteger.ZERO) > 0) {
				propertyStr.append(parseGoodsToString(goodsId, value)).append(reqex);
			}
		}
		if (propertyStr.length() > 1) {
			return propertyStr.substring(0, propertyStr.length() - 1);
		}else {
			return "";
		}
	}

	public static String parsePropertyToString(List<Property> propertyList, String split) {
		if (null == propertyList) {
			return "";
		}
		StringBuilder stringBuilder = new StringBuilder();
		for (Property property : propertyList) {
			stringBuilder.append(parsePropertyToString(property));
			stringBuilder.append(split);
		}
		stringBuilder.deleteCharAt(stringBuilder.length() - 1);
		return stringBuilder.toString();
	}

	public static String parseGoodsToString(int goodsId, BigInteger value) {
		return goodsId + "=" + value.toString();
	}

	public static boolean isTheSameGood(Property ap, Property bp){
		Map<Integer, BigInteger> aGoodMap = ap.getGoods();
		Map<Integer, BigInteger> bGoodMap = bp.getGoods();
		if(aGoodMap.size() != bGoodMap.size()){
			return false;
		}
		for(int goodId : aGoodMap.keySet()){
			if(!bGoodMap.containsKey(goodId) || bGoodMap.get(goodId).compareTo(aGoodMap.get(goodId)) != 0){
				return false;
			}
		}
		return true;
	}

	public static String parseMapToPropertyString(Map<Integer, Integer> map){
		StringBuilder stringBuilder = new StringBuilder();
		for(int goodId : map.keySet()){
			stringBuilder.append(parseGoodsToString(goodId, BigInteger.valueOf(map.get(goodId)))).append(";");
		}
		if(stringBuilder.length() > 1){
			return stringBuilder.substring(0, stringBuilder.length() - 1);
		}else {
			return "";
		}
	}

	public static void main(String[] args){
		Property property1 = parseNewStringToProperty("101000=1,50");
		System.out.println(parsePropertyToString(property1));
		Property property2 = parseNewStringToProperty("101000=1,50|101001=50,50");
		System.out.println(parsePropertyToString(property2));
		Property property3 = parseNewStringToProperty("101000=1,50#101002=50,60|101001=50,50#101003=50,999");
		System.out.println(parsePropertyToString(property3));
		Property property4 = parseNewStringToProperty("101000=50;101001=50;101002=50,999#101002=50,60|101005=50,50#101006=50,999");
		System.out.println(parsePropertyToString(property4));
	}
}
